<?php

/**
 * Array Operations
 * @package Nina
 * @author John Main <john@thedaddy.org>
 */
class Nina_Array
{
	protected $arr;
	
	/**
	 * Constructor
	 * @param array [$arr=array()] The array to manipulate
	 */
	public function __construct($arr = array()) {
		$this->arr = $arr;
	}
	
	/**
	 * Get the array
	 * @return array
	 */
	public function get() {
		return $this->arr;
	}

	/**
	 * Check if the array contains the given value
	 * @param mixed $value The value
	 * @return boolean
	 */
	public function contains($value) {
		return in_array($value, $this->arr);
	}

	/**
	 * Get the length of the array
	 * @return integer
	 */
	public function length() {
		return count($this->arr);
	}

	/**
	 * Get the first element of the array
	 * @return mixed
	 */
	public function first() {
		if($this->length() > 0)
			return $this->arr[0];
		else
			return null;
	}

	/**
	 * Get the last element of the array
	 * @return mixed
	 */
	public function last() {
		if($this->length() > 0)
			return $this->arr[count($this->arr)-1];
		else
			return null;
	}

	/**
	 * Add a value to the end of the array
	 * @param mixed $value The value
	 * @return integer
	 */
	public function push($value) {
		return array_push($this->arr, $value);
	}

	/**
	 * Remove a value from the end of the array and return
	 * @param mixed $value The value
	 * @return mixed
	 */
	public function pop() {
		return array_pop($this->arr);
	}

	/**
	 * Remove a value from the front of the array and return
	 * @param mixed $value The value
	 * @return mixed
	 */
	public function shift() {
		return array_shift($this->arr);
	}

	/**
	 * Add a value to the front of the array
	 * @param mixed $value The value
	 * @return integer
	 */
	public function unshift($value) {
		return array_unshift($this->arr, $value);
	}

	/**
	 * Return a random value from the array
	 * @return mixed
	 */
	public function random() {
		return $this->arr[array_rand($this->arr)];
	}

	/**
	 * Sort the array by values
	 * @param boolean [$forward=true] Sort it in a forwards direction
	 * @return array
	 */
	public function sort($forward = true) {
		$tmp_arr = $this->arr;
		if($forward) sort($tmp_arr);
		else rsort($tmp_arr);
		return $tmp_arr;
	}

	/**
	 * Randomise the array
	 * @return array
	 */
	public function shuffle() {
		$tmp_arr = $this->arr;
		shuffle($tmp_arr);
		return $tmp_arr;
	}

	/**
	 * Compute the differnce betwwen the two arrays
	 * @param array $new_arr The other array
	 * @return array
	 */
	public function diff($new_arr) {
		return array_diff($this->arr, $new_arr);
	}

	/**
	 * Run the callback filter on each value of the array
	 * True values from the callback function mean that the value will be included in the resulting array
	 * @param string [$callback=null] The callback function
	 * @return array
	 */
	public function select($callback = null) {
		return array_filter($this->arr, $callback);
	}

	/**
	 * Run the callback function on each value of the array
	 * The values returned from the callback function will be in the resulting array, with keys being preserved
	 * @param array $new_arr The other array
	 * @return array
	 */
	public function collect($callback) {
		return array_map($callback, $this->arr);
	}

	/**
	 * Merge another array into this one
	 * @param array $new_arr The other array
	 * @return array
	 */
	public function merge($new_arr) {
		return array_merge($this->arr, $new_arr);
	}

	/**
	 * Remove any duplicates from the array
	 * @return array
	 */
	public function unique() {
		return array_unique($this->arr);
	}
	
	/**
	 * Join the array values as natural language
	 * @param string [$joiner='and'] The joining text
	 * @param string [$callback=null] The callback function
	 * @param mixed [$argument=null] Any argument for the callback function
	 * @return string
	 */
	public function displayJoin($joiner = 'and', $callback = null, $argument = null) {
		if($callback) {
			if($argument) {
				if(function_exists($callback))
					$text = call_user_func($callback, $this->first(), $argument);
				else
					$text = $this->first()->$callback($argument);
			}
			else {
				if(function_exists($callback))
					$text = call_user_func($callback, $this->first());
				else
					$text = $this->first()->$callback();
			}
		}
		else
			$text = $this->first();
		
		if($this->length() > 1) {
			for($i = 1; $i < $this->length(); $i++) {
				if($i < $this->length() - 1)
					$text .= ', ';
				else
					$text .= " $joiner ";
	
				if($callback) {
					if($argument)
						if(function_exists($callback))
							$text .= call_user_func($callback, $this->arr[$i], $argument);
						else
							$text .= $this->arr[$i]->$callback($argument);
					else
						if(function_exists($callback))
							$text .= call_user_func($callback, $this->arr[$i]);
						else
							$text .= $this->arr[$i]->$callback();
				}
				else
					$text .= $this->arr[$i];
			}
		}
		
		return $text;
	}
}	